#-*- coding:Utf-8 -*-
#!/usr/bin/env python


import direct.directbase.DirectStart

from direct.showbase.DirectObject import DirectObject
from pandac.PandaModules import * 
from direct.task import Task 
from direct.distributed.PyDatagram import PyDatagram 
from direct.distributed.PyDatagramIterator import PyDatagramIterator
from direct.gui.OnscreenText import OnscreenText

from Client import *
from Niveau import *
import re
import sys

#Classe Joueur
class Joueur(DirectObject):
    def __init__(self):
        #Infos diverses et variées, dont pos, skin, carac etc mais aussi liste des infos sur les autres joueurs (et tout ce qu'envoi le serv d'ailleurs)
        self.ident=-1
        self.nom="bob"
        self.model="../assets/eggs/panda-model.egg"
        self.scale=0.002
        self.posx=0
        self.posy=0
        self.posz=0
        self.player = loader.loadModel(self.model)
        self.player.setPos(self.posx, self.posy, self.posz)
        self.autresJoueurs={}
        self.niveau=-1
        self.nbEquipe=-1
        
        # Connection au serveur
        self.client = Client("127.0.0.1", 9099, compress=True)
        
        # Creation d'une tache de traitement
        taskMgr.doMethodLater(0, self.traitementTask, "update")
        #taskMgr.add(self.updateMove, "move")
        self.keyboardSetup()#Prise en compte clavier

    #Nom à changer, reception des données, traitement, renvoi (au serveur)
    def traitementTask(self, task):

        #print "Received: " + str(self.client.getData())
        #print "Connected: " + str(self.client.getConnected())
        
        data=self.client.getData()
        #print "{0} >>>> {1}".format(data,type(data))

        #Si trame non vide
        if(len(data) !=0):
            #Assignation numéro connection
            if self.ident==-1:
                if data[0]:
                    self.ident=data[0]["valident"]
                    data.remove(data[0])
        
            #Sauvegarde et affichage de la map
            if data:
                self.svgMap(data[0]) #TODO AU DEBUT ET SUR CHANGEMENT
                self.afficherWorld()#TODO AU DEBUT ET SUR CHANGEMENT
                self.player.setScale(self.scale)
                self.player.reparentTo(render)
        
        return Task.again

    #Sauvegarde du niveau
    def svgMap(self, data):
        self.niveau= Niveau(data['partie'][0], data['world']['murs'], data['world']['world'],data['partie'][1],data['partie'][2],data['partie'][3])
        self.nbEquipe=data['partie'][0]
        
    #affichage du niveau - identique à servgame.py
    def afficherWorld(self):
        #Pour chaque murs du labyrinthe on crée un model, correspondant à un model et des positions
        for i in range(len(self.niveau.laby3D["murs"])):
            mur=loader.loadModel(self.niveau.laby3D["boxmodel"])
            mur.setScale(self.niveau.laby3D["scale"])
            mur.setPos(self.niveau.laby3D["murs"][i][0],self.niveau.laby3D["murs"][i][1],self.niveau.laby3D["murs"][i][2])
            mur.reparentTo(render)#Affichage

        #Chargement centre, spawns, paniers
        #Egg des bords, echelle des bords, egg du centre, echelle du centre, echelle des paniers
        self.initSpawnCentre("../assets/eggs/untitled", 0.5, "../assets/eggs/boxold", 10, 10)
        
        
    #Mise à jour de la position du perso
    def updatePosition(self, posx, posy, posz):
        self.posx=posx
        self.posy=posy
        self.posz=posz
        self.player.setPos(posx, posy, posz)
        self.player.reparentTo(render)

    #Mise à jour de la caméra et du joueur
    def updateMove(self, task):
        self.updatePlayer()
        self.updateCamera()
        return Task.cont

    #Interception constante des intéractions clavier
    #Permet d'assigner une action à une touche préssée
    def keyboardSetup(self):
        self.keyMap = {"gauche":0, "droite":0, "devant":0, "derriere":0}
        self.accept("escape", sys.exit)
        self.accept("z", self.setKey, ["devant",1])
        self.accept("z-up", self.setKey, ["devant",0])
        self.accept("s", self.setKey, ["derriere",1])
        self.accept("s-up", self.setKey, ["derriere",0])
        self.accept("q", self.setKey, ["gauche",1])
        self.accept("q-up", self.setKey, ["gauche",0])
        self.accept("d", self.setKey, ["droite",1])
        self.accept("d-up", self.setKey, ["droite",0])
        base.disableMouse() # or updateCamera will fail!

    #Assignation des effets d'intéraction
    def setKey(self, key, value):
        self.keyMap[key] = value

    #Mise à jour du joueur pour affichage
    def updatePlayer(self):
        if (self.keyMap["devant"]!=0):
            # faster you go, quicker you climb
            OnscreenText(text = 'Devant', pos = (-0.5, 0.02), scale = 0.07)
            self.posx=self.posx+1
        elif (self.keyMap["derriere"]!=0):
            self.posx=self.posx-1
            #self.player.setX(self.player.getX()+1*self.speed)

        # Left and Right
        if (self.keyMap["gauche"]!=0):
            self.posy=self.posy+1
            #self.player.setY(self.player.getY()-1*self.speed)
        elif (self.keyMap["droite"]!=0 ):
            self.posy=self.posy-1
            #self.player.setY(self.player.getY()+1*self.speed)

    #Mise en place caméra
    #Todo : améliorer
    def updateCamera(self):
        # see issue content for how we calculated these:
        base.camera.setPos(self.player, 10, 10, 10)
        base.camera.setHpr(self.player,20, 0, 0)



    #Egg des bords, echelle des bords, egg du centre, echelle du centre, echelle des paniers
    def initSpawnCentre(self, eggBords, scaleBords, eggCentre, scaleCentre, scalePaniers):
        #Affichages des bords de la map
        lgLab=self.niveau.labyrinthe.taille #Nombre de parcelles par ligne
	lgParc=self.niveau.labyrinthe.parcelles[0].taille
	nbCasesLigne=lgLab*lgParc
	y=-1
	x=-1
        if(self.nbEquipe==4):
            equipe=True
        else :
            equipe=False
        while (x != nbCasesLigne):
            if(self.nbEquipe<=2):
                mur=loader.loadModel(eggBords)
                mur.setScale(scaleBords)
                mur.setPos(x,y,0)
                mur.reparentTo(render)
            elif (self.nbEquipe>2):
                if(equipe==True):
                    if((x<(((nbCasesLigne-1)/2)-((lgParc-1)/2)+1)or x>(((nbCasesLigne-1)/2)+((lgParc-1)/2))+1)):
                        mur=loader.loadModel(eggBords)
                        mur.setScale(scaleBords)
                        mur.setPos(x,y,0)
                        mur.reparentTo(render)
                else :
                    mur=loader.loadModel(eggBords)
                    mur.setScale(scaleBords)
                    mur.setPos(x,y,0)
                    mur.reparentTo(render)
            x=x+1
            if( x== nbCasesLigne and y==-1):
                x=-1
                y=nbCasesLigne
                equipe=True
                if(self.nbEquipe==4):
                    equipe=True
                
        y=-1
        x=-1
        while (y != nbCasesLigne):
            if(y<(((nbCasesLigne-1)/2)-((lgParc-1)/2)+1)or y>(((nbCasesLigne-1)/2)+((lgParc-1)/2))+1):
                mur=loader.loadModel(eggBords)
                mur.setScale(scaleBords)
                mur.setPos(x,y,0)
                mur.reparentTo(render)
            y=y+1
            if( y== nbCasesLigne and x==-1):
                y=-1
                x=nbCasesLigne


        #######Les Spawns
        #Nord
            pos=((lgLab-1)/2)*lgParc
            panier=loader.loadModel("../assets/eggs/boxold")
            panier.setScale(scalePaniers)
            panier.setPos(-scalePaniers,pos,0)
            panier.reparentTo(render)

        #Sud
            panier=loader.loadModel("../assets/eggs/boxold")
            panier.setScale(scalePaniers)
            posy=(lgLab*lgParc)
            panier.setPos(posy,pos,0)
            panier.reparentTo(render)

        #Est
            if(self.nbEquipe>=3):
                pos=((lgParc)*((lgLab-1)/2))
                panier=loader.loadModel("../assets/eggs/boxold")
                panier.setScale(scalePaniers)
                posy=(lgLab*lgParc)
                panier.setPos(pos,posy,0)
                panier.reparentTo(render)
       
         #Ouest
            if(self.nbEquipe==4):
                pos=((lgParc)*((lgLab-1)/2))
                panier=loader.loadModel("../assets/eggs/boxold")
                panier.setScale(scalePaniers)
                panier.setPos(pos,-scalePaniers,0)
                panier.reparentTo(render)
        
        #Si mode randball on ajoute centre et paniers  
        if(self.niveau.modeJeu==1):
            #Le centre
            pos=((lgLab*lgParc)/2)-(lgParc/2)
            centre=loader.loadModel(eggCentre)
            centre.setScale(scaleCentre)
            centre.setPos(pos,pos,0)
            centre.reparentTo(render)
            
            #######Les paniers
            ####Nord
            pos=((lgLab-1)/2)*lgParc
            panier=loader.loadModel("../assets/eggs/boxold")
            panier.setScale(scalePaniers)
            panier.setPos(0,pos,0)
            panier.reparentTo(render)

            ####Sud
            panier=loader.loadModel("../assets/eggs/boxold")
            panier.setScale(scalePaniers)
            posy=(lgLab*lgParc)-scalePaniers
            panier.setPos(posy,pos,0)
            panier.reparentTo(render)
            
            ####Est
            if(self.nbEquipe>=3):
                pos=((lgParc)*((lgLab-1)/2))
                panier=loader.loadModel("../assets/eggs/boxold")
                panier.setScale(scalePaniers)
                posy=(lgLab*lgParc)-scalePaniers
                panier.setPos(pos,posy,0)
                panier.reparentTo(render)

                
            ####Ouest
            if(self.nbEquipe==4):
                pos=((lgParc)*((lgLab-1)/2))
                panier=loader.loadModel("../assets/eggs/boxold")
                panier.setScale(scalePaniers)
                panier.setPos(pos,0,0)
                panier.reparentTo(render)
            
w = Joueur()
run()
